package net.oschina.arvin.dbjava.util;

import com.alibaba.fastjson.JSON;
import net.oschina.arvin.dbjava.model.Column;
import net.oschina.arvin.dbjava.type.*;

import java.util.ArrayList;
import java.util.List;

/**
 * 数据库
 *
 * @author Arvin
 * @time 2017/9/28 18:28
 */
public class DBJavaTypeMap {

    /**
     * 默认的java类型
     */
    public static final Class<?> DEFAULT_JAVA_TYPE = String.class;

    /**
     * db 到 java 数据类型转换器列表
     */
    private static final List<DBJavaTypeConverter> dbJavaTypeConverterList = new ArrayList<DBJavaTypeConverter>();

    static {
        registerDBJavaTypeConverter(new BooleanDBJavaTypeConverter());
        registerDBJavaTypeConverter(new IntDBJavaTypeConverter());
        registerDBJavaTypeConverter(new LongDBJavaTypeConverter());
        registerDBJavaTypeConverter(new BigIntegerDBJavaTypeConverter());
        registerDBJavaTypeConverter(new FloatDBJavaTypeConverter());
        registerDBJavaTypeConverter(new DoubleDBJavaTypeConverter());
        registerDBJavaTypeConverter(new BigDecimalDBJavaTypeConverter());
        registerDBJavaTypeConverter(new DateDBJavaTypeConverter());
        registerDBJavaTypeConverter(new TimestampDBJavaTypeConverter());
        registerDBJavaTypeConverter(new TimeDBJavaTypeConverter());
        registerDBJavaTypeConverter(new ByteArrayDBJavaTypeConverter());
        registerDBJavaTypeConverter(new StringDBJavaTypeConverter());
    }

    /**
     * 注册db属性到java类型的转换器
     *
     * @param dbJavaTypeConverter 转换器
     */
    public static void registerDBJavaTypeConverter(DBJavaTypeConverter dbJavaTypeConverter) {
        if (null != dbJavaTypeConverter) {
            if (!isDBJavaTypeConverterExists(dbJavaTypeConverter)) {
                dbJavaTypeConverterList.add(dbJavaTypeConverter);
            }
        }
    }

    public static boolean isDBJavaTypeConverterExists(DBJavaTypeConverter dbJavaTypeConverter) {
        if (null == dbJavaTypeConverter) {
            return false;
        }

        if (dbJavaTypeConverterList.isEmpty()) {
            return false;
        }
        for (DBJavaTypeConverter converter : dbJavaTypeConverterList) {
            if (dbJavaTypeConverter.getClass() == converter.getClass()) {
                return true;
            }
        }

        return false;
    }

    public static List<DBJavaTypeConverter> getDbJavaTypeConverterList() {
        return dbJavaTypeConverterList;
    }

    /**
     * <pre>
     * 转换为java类型
     *
     * 参考链接： https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-type-conversions.html
     *
     * </pre>
     *
     * @param column                数据库列
     * @param toBoolForLenOneNumber 是否将长度为1的TINYINT和BIT转换成boolean
     * @param useUtilDate           使用使用 java.util.Date
     * @param wrapMode              是否使用包装类，如int--> Integer (注意只有允许null的才会转换， 不允许null的会抛异常)
     * @return
     */
    public static Class<?> getJavaTypeFromMysqlColumn(Column column, boolean toBoolForLenOneNumber, boolean useUtilDate, boolean wrapMode) {
        for (DBJavaTypeConverter converter : dbJavaTypeConverterList) {
            Class<?> javaType = converter.convertToJavaType(column, toBoolForLenOneNumber, useUtilDate, wrapMode);
            if (null != javaType) {
                return javaType;
            }
        }
        String message = "Unknown column, use default String, can't convert to javaType for column : " + JSON.toJSONString(column);
        System.out.println(message);
        return DEFAULT_JAVA_TYPE;
    }

    /**
     * 转换为java类型, boolean类型的仍然是boolean类型， 并且使用包装类型
     *
     * @param column
     * @return
     */
    public static Class<?> getJavaTypeFromMysqlColumn(Column column) {
        return getJavaTypeFromMysqlColumn(column, false, false, true);
    }
}
